package com.june.spider.service.impl;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.june.spider.exception.URLNotFoundException;
import com.june.spider.model.LiveVideoRoom;
import com.june.spider.service.SpiderService;
import com.june.spider.util.SpringBeanHolder;

/**
 * 参考SpringMVC中HandlerMethodArgumentResolverComposite实现
 * @author June
 */
@Service("spiderService")
public class SpiderServiceComposite implements SpiderService {
	
	/**
	 * 用于保存SpiderService实例的集合
	 */
	private final Collection<SpiderService> spiderServices = new LinkedList<>();
	
	/**
	 * 缓存Map集合
	 */
	private final Map<String, SpiderService> spiderServicesCache = new ConcurrentHashMap<>();

	private static final Logger LOG = LoggerFactory.getLogger(SpiderServiceComposite.class);
	
	@Override
	public List<LiveVideoRoom> getRoomList(String url) {
		SpiderService spiderService = getSpiderService(url);
		if (spiderService == null) {
			LOG.error("未知url: " + url);
			throw new URLNotFoundException("未知网址");
		}
		return spiderService.getRoomList(url);
	}
	
	public SpiderServiceComposite addServices(SpiderService... services) {
		addServices(Arrays.asList(services));
		return this;
	}
	
	public SpiderServiceComposite addServices(Collection<? extends SpiderService> services) {
		if (services != null) {
			spiderServices.addAll(services);
		}
		return this;
	}
	
	public Collection<SpiderService> getServices() {
		return Collections.unmodifiableCollection(spiderServices);
	}
	
	/**
	 * {@inheritDoc}
	 * <p>此处仅抛出<tt>UnsupportedOperationException</tt>
	 * @throws java.lang.UnsupportedOperationException
	 */
	@Override
	public String getHost() {
		throw new UnsupportedOperationException();
	}
	
	/**
	 * {@inheritDoc}
	 * <p>此处仅抛出<tt>UnsupportedOperationException</tt>
	 * @throws java.lang.UnsupportedOperationException
	 */
	@Override
	public String getRegex() {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 * <p>此处仅抛出<tt>UnsupportedOperationException</tt>
	 * @throws java.lang.UnsupportedOperationException
	 */
	@Override
	public boolean supportsUrl(String url) {
		throw new UnsupportedOperationException();
	}
	
	/**
	 * {@inheritDoc}
	 * <p>此处仅抛出<tt>UnsupportedOperationException</tt>
	 * @throws java.lang.UnsupportedOperationException
	 */
	@Override
	public List<LiveVideoRoom> parse(String html) {
		throw new UnsupportedOperationException();
	}
	
	/**
	 * 获取能够处理指定url的spiderService对象返回
	 * @param url
	 * @return spiderService对象，或者null
	 */
	private SpiderService getSpiderService(String url) {
		beforeGetService();
		// 先从缓存中查找
		SpiderService result = spiderServicesCache.get(url);
		if (result != null) {
			// 找到则直接返回
			return result;
		}
		// 缓存中没有，则从列表中查找
		result = spiderServices.stream()
				.filter(service -> service.supportsUrl(url))
				.findFirst()
				.orElse(null);
		if (result != null) {
			// 将结果放入缓存
			spiderServicesCache.put(url, result);
		}
		return result;
	}

	/**
	 * 使用IOC容器中的Bean实例初始化spiderServices集合
	 */
	private void beforeGetService() {
		// 从IOC容器中取出SpiderService接口的所有实例Bean
		Map<String, SpiderService> beanMap = SpringBeanHolder.getBeanMapByType(SpiderService.class);
		if (!CollectionUtils.isEmpty(beanMap)) {
			Collection<SpiderService> services = beanMap.values();
			// 把当前对象移除（因为当前对象也是SpiderService接口的一个实例）
			services.remove(this);
			// 将IOC容器中取出的SpiderService实例Bean添加到集合中
			spiderServices.addAll(services);
		}
	}

}
